package com.hfb.mashibing.alip8.diamondsquarealgorithm.class01;

import java.util.LinkedList;

/**
 * 算法：滑动窗口
 *
 * 题目：
 * 找到最大值减去最小值小于等于一个数值的子数组数量
 *
 * 如果L~R范围上达标,那么里面的任何一个子数组都达标
 *
 * 如果L~R范围上不达标,当R向右扩时,必定不达标。
 *
 * 所有我们只需要遍历一次，每次找到以L开头的子数组达标的子数组数量。
 *
 * 方案：
 * 使用滑动窗口，这里用到两个滑动窗口。
 * 特别简单，就是保持队列里面的大小顺序，
 * 当加入的数值破坏了规矩，那么就把队列的队头给弹出。
 */
public class Code02_AllLessNumSubArray {

    public static void main(String[] args) {
        System.out.println(getNum(new int[]{5,4,1,2,6,2,3,3}, 6));
    }

    public static int getNum(int[] arr ,int num){
        if (arr == null || arr.length == 0) {
            return 0;
        }
        LinkedList<Integer> qmin = new LinkedList<Integer>();
        LinkedList<Integer> qmax = new LinkedList<Integer>();
        int L = 0;
        int R = 0;
        int res = 0;
        while(L < arr.length){
            //L确定了之后,R往右扩.
            while(R < arr.length){
                while(!qmin.isEmpty() && arr[qmin.peekLast()] >= arr[R]){
                    qmin.pollLast();
                }
                qmin.addLast(R);
                while(!qmax.isEmpty() && arr[qmax.peekLast()] <= arr[R]){
                    qmin.pollLast();
                }
                qmax.addLast(R);
                //如果达标了,就可以得出R-L个子数组
                if(arr[qmax.getFirst()] - arr[qmin.getFirst()] > num){
                    break;
                }
                R++;
            }
            if (qmin.peekFirst() == L) {
                qmin.pollFirst();
            }
            if (qmax.peekFirst() == L) {
                qmax.pollFirst();
            }
            res += R -1;
            //如果R了不能扩了,就扩L
            L++;
        }
        return res;
    }
}
